/**
 * @program: smart-school
 * @description: 具体实现类
 * @author: Qing Miao Dan Xie
 * @create: 2022-06-01 14:52
 **/
package org.jeecg.modules.analysisachievement.reports.service.impl;

import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.RowRenderData;
import com.deepoove.poi.data.Rows;
import com.deepoove.poi.data.TableRenderData;
import com.deepoove.poi.data.Tables;
import com.deepoove.poi.data.style.TableStyle;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.vo.SysTenantVo;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.achexamination.service.IAchExaminationService;
import org.jeecg.modules.analysisachievement.achclasses.service.IAchClassAchievementExamScoreService;
import org.jeecg.modules.analysisachievement.achclasses.service.IAchClassSubjectScoreService;
import org.jeecg.modules.analysisachievement.achclasses.vo.AchClassAchievementExamScoreVo;

//import org.jeecg.modules.analysisachievement.reports.entity.TitleInfo;
import org.jeecg.modules.analysisachievement.reports.entity.TitleInfo;
import org.jeecg.modules.analysisachievement.reports.service.AnalysisReportService;
import org.jeecg.modules.analysisachievement.reports.service.IDataList2TableUtilService;
import org.jeecg.modules.common.api.IRow2ColTransfer;
import org.jeecg.modules.common.baseentity.Row2ColModel;
import org.jeecg.modules.grade.service.ICouGradeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


import javax.servlet.http.HttpServletResponse;
import java.util.*;

@Service
@Slf4j
public class AnalysisReportServiceImpl implements AnalysisReportService {

    @Autowired
    private ISysBaseAPI sysBaseAPI;
    @Autowired
    private IRow2ColTransfer row2ColTransfer;
    @Autowired
    IAchClassSubjectScoreService achClassSubjectScoreService;

    @Autowired
    IAchClassAchievementExamScoreService classAchievementExamScoreService;

    private HashMap<String, Object> baseInfo = new HashMap<>();

    @Autowired
    private ICouGradeService gradeService;

    @Autowired
    private IAchExaminationService examinationService;

    @Autowired
    private IDataList2TableUtilService dataList2TableUtilService;

    private void initUserInfo(String tenantId) {
        SysTenantVo sysTenantVo = sysBaseAPI.getSysTenant(tenantId);
        baseInfo.put("schoolName", sysTenantVo.getName());
    }

    /**
     * 传入Param 和实体类使用此方法解析
     *
     * @param achClassAchievementExamScoreVo
     * @param queryParam
     */
    private void parseParam2map(AchClassAchievementExamScoreVo achClassAchievementExamScoreVo, Map<String, String> queryParam) {
        baseInfo.put("gradeId", achClassAchievementExamScoreVo.getGradeId());
        baseInfo.put("schoolYearId", queryParam.get("schoolYearId"));
        baseInfo.put("semesterId", queryParam.get("semesterId"));
//        baseInfo.put("classId", achClassAchievementExamScoreVo.getClassId());
        baseInfo.put("examinationId", achClassAchievementExamScoreVo.getExaminationId());
        baseInfo.put("semesterName", queryParam.get("semesterName"));
        baseInfo.put("schoolYearName", queryParam.get("schoolYearName"));
        prepareData();
    }

    private void prepareData() {
        if (Objects.nonNull(baseInfo.get("gradeId"))) {
            baseInfo.put("gradeName", gradeService.getById((String) baseInfo.get("gradeId")).getGradeName());
        }
        if (Objects.nonNull(baseInfo.get("examinationId"))) {
            baseInfo.put("examName", examinationService.getById((String) baseInfo.get("examinationId")).getExaminationName());
        }
    }

    private TitleInfo initData() {
        TitleInfo titleInfo = new TitleInfo();
        titleInfo.setSchoolName((String) baseInfo.get("schoolName"));
        titleInfo.setGradeName((String) baseInfo.get("gradeName"));
        titleInfo.setExamName((String) baseInfo.get("examName"));
        return titleInfo;
    }


    /**
     * POI-tl实现类
     * <p>
     * 没有处理空值问题
     *
     * @param achClassAchievementExamScoreVo
     * @param queryParam
     * @param response
     */
    @Override
    public XWPFTemplate PoiGenerator(String templateModelId,AchClassAchievementExamScoreVo achClassAchievementExamScoreVo, Map<String, String> queryParam, HttpServletResponse response) throws NoSuchFieldException, IllegalAccessException {
        // templatePath =  templateModelId.getFilePath(), 根据模板id设置模板文件路径：从数据库字典码中配置或从模板表中配置

        String templatePath = "jeecg-boot-module-analysis\\src\\main\\resources\\templates\\student-report.docx";
        initUserInfo(achClassAchievementExamScoreVo.getTenantId());
        parseParam2map(achClassAchievementExamScoreVo, queryParam);
        XWPFTemplate template = XWPFTemplate.compile(templatePath);

        getDocTableStyle(template.getXWPFDocument(),3,20);
        if (baseInfo.isEmpty()) {
            log.error("Init baseMap Info Error...");
            throw new RuntimeException();
        }
        HashMap<String, Object> dataMap = new HashMap<>();
        List<AchClassAchievementExamScoreVo> vos = classAchievementExamScoreService.queryAchClassAchievementExamScoreVoLists(achClassAchievementExamScoreVo, queryParam);

        // clazzT 类型
        // groupFields 1.固定分组属性名称
        // groupFieldsAsName 2.固定分组属性显示别名
        // row2colsKeyFields  3.行转列动态列对应的关键属性字段，例如：科目字段（值是=语文 英语 数学）
        // newColsValueByFields 4.行转列动态列对应的值字段，允许空：例如：成绩字段（值是=98.5 99 59.5）
        // newColsnewColsValueUnitSymboles 5.动态列对应的单位符号，允许空，例如：“%” “人” “个”等
        // groupCalculationFun  6.聚聚合计算函数，支持[sum,count,max,min]不区分大小写
        // groupCalculationFunForValueField 7.聚合函数作用字段
        // groupCalculationAsColName 8.计算值列名字符串=列名+字符串，值=“Calculation”，所得列名=“语文Calculation”
        // newValueWeightCoefficientFieldes  //9.聚合函数使用的权重系数字段
        // newWeightCoefficientAsColName  //10.权重系数列名
        Class clazzT = AchClassAchievementExamScoreVo.class;
        String[] groupFields = new String[]{"className","avgClassAchievementScore","classStudentExamCount","classStudentAllCount"}; //1.固定分组属性名称
        String[] groupFieldsAsName = new String[]{"班级","平均分","参考人数","总人数"};             //2.固定分组属性显示别名
        String[] row2colsKeyFields = new String[]{"standItemAliasname"}; //优良名称 //3.行转列动态列对应的关键属性字段
        Map<String,String>[] row2colsKeyFieldsDict = null ;
        String[] newColsValueByFields = new String[]{"analysisYlv","analysisYlrs","rankYlvClass"};  //4.行转列动态列对应的值字段, 优良率数值取值字段
        String[] newColsValueUnitSymboles = new String[]{"%","人",""};            //5.动态列对应的单位符号，允许空，例如：“%” “人” “个”等
        String[] groupCalculationFun = new String[]{"sum","count"} ;                          //6.聚聚合计算函数，支持[sum,count,max,min]不区分大小写
        String[] groupCalculationFunForValueField = new String[]{"analysisYlrs","analysisYlv"};              //7.聚合函数作用字段，必须是newColsValueByFields中的字段不能是别的字段
        String[][] groupCalculationAsColName = new String[][]{{"人数总和","人数数量"},{"率和","率量"}};                          //8.计算值列名字符串=列名+字符串，值=“Calculation”，所得列名=“语文Calculation”
        String newValueWeightCoefficientFieldes = "classStudentAllCount"; /*9.聚合函数使用的权重系数字段,*/
        String newWeightCoefficientAsColName = "权重系数"; //10.权重系数列名

        Row2ColModel row2ColModel = new Row2ColModel(clazzT,groupFields,groupFieldsAsName,row2colsKeyFields,row2colsKeyFieldsDict,newColsValueByFields,newColsValueUnitSymboles,groupCalculationFun,groupCalculationFunForValueField,groupCalculationAsColName,newValueWeightCoefficientFieldes,newWeightCoefficientAsColName);

        TableRenderData jsonObjList2Table = dataList2TableUtilService.getTableByDataListForRow2Col(vos,  row2ColModel);//Tables.of(tablejsonObjList).border(BorderStyle.DEFAULT).create();
        TableStyle tableStyle= jsonObjList2Table.getTableStyle();

        jsonObjList2Table.setTableStyle(tableStyle);

        dataMap.put("tableClassYlv",jsonObjList2Table);

        // 第0行居中且背景为蓝色的表格
        String[] row1111= new String[]{"","",};


        RowRenderData table1Row0 = Rows.of("姓名", "学历").textColor("FFFFFF").bgColor("4472C4").center().create();
        RowRenderData table1Row1 = Rows.create("李四", "博士");
        TableRenderData t = Tables.create(table1Row0, table1Row1);


        dataMap.put("table1", Tables.create(table1Row0, table1Row1));

        if (vos.size() >= 1) {
            LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
            Configure config = Configure.builder()
                    .bind("vos", policy)
                    .build();
            template = XWPFTemplate.compile(templatePath, config);
        }
        //塞入基础头信息
        dataMap.put("titleInfo", initData());
        dataMap.put("vos", vos);
        template.render(dataMap);

        getDocTableStyle(template.getXWPFDocument(),3,20);
        //输出到文件流：保存到服务器指定路径下
//        try {
////            template.writeAndClose(new FileOutputStream("output.docx"));
//            OutputStream out = response.getOutputStream();
//            BufferedOutputStream bos = new BufferedOutputStream(out);
//            template.write(bos);
//            bos.flush();
//            out.flush();
//            template.write(new FileOutputStream("output.docx"));
//            PoitlIOUtils.closeQuietlyMulti(template, bos, out);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
        return template;
    }
    public void getDocTableStyle(XWPFDocument doc,int minColSize,int maxColSize){
        TableStyle tableStyle;
        List<XWPFTable> tabList =  doc.getTables();
        for  (XWPFParagraph paragraph : doc.getParagraphs()) {
            int pos = 0;
            System.out.println(paragraph.getClass() + ",paragraph=" + paragraph.toString());
            for (XWPFRun run : paragraph.getRuns()) {
                System.out.println("run : " + run.toString());
                System.out.println("run.getStyle() : " + run.getStyle().toString());
//
//                for (char c : run.text().toCharArray()) {
//                    System.out.print(c);
//
//                    pos++;
//
//                }

                System.out.println();
            }
        }

        for(XWPFTable ti : tabList){
            ti.getPart().getRelationParts();

            System.out.println(ti.getClass().getName()+",getStyleID="+ti.getStyleID()+",getColBandSize="+ti.getColBandSize());
            System.out.println(ti.toString());
            for(POIXMLDocumentPart.RelationPart rpx : ti.getPart().getRelationParts()){
                if("org.apache.poi.xwpf.usermodel.XWPFStyles".equals(rpx.getDocumentPart().getClass().getName()) || "XWPFStyles".equals(rpx.getDocumentPart().getClass().getSimpleName())){
                    System.out.println(",ti.getStyleID="+ti.getStyleID()+"，ti.getText()="+ti.getText());
                    System.out.println("，rpx.getClass()="+rpx.getClass().toString()+"--rpx.toString()="+rpx.toString());
                    ;
                    System.out.println(rpx.getDocumentPart().getClass().getName()+"=="+rpx.getDocumentPart().getClass().getSimpleName()+"=="+rpx.getDocumentPart().toString());
                    POIXMLDocumentPart ppart1 = ti.getPart();
//                    PackagePart ppart2 = oConvertUtils.isEmpty(ti.getStyleID()) ? null : doc.getPartById(ti.getStyleID());
//                    String ppart2Str = oConvertUtils.isEmpty(ppart2)? "" : ppart2.toString();
//                    System.out.println(ppart1.toString()+ppart2Str);
                    System.out.println(ppart1.toString());

                }
            }

        }
    }
}
